﻿using System;
using System.ComponentModel;
using System.ServiceModel;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Universe.WCF.Behaviors;

namespace Universe.TrafficProfiler
{
    public partial class ProfilerForm : Form
    {
        private ListenerState _State;
        private ProcessListModel.ProcessInfo _Zero;
        

        private TrafficPair OnStart, Sum;
        private Thread _thread;

        public ProfilerForm()
        {
            InitializeComponent();
        }

        public ProfilerForm(ProcessListModel.ProcessInfo zero): this()
        {
            if (zero == null)
                throw new ArgumentNullException("zero");

            _Zero = zero;
            UpdateState1(ListenerState.Zero);

            this.Text = "Profiler #" + zero.Id + ": " + zero.File;

            _thread = new Thread(
                delegate()
                    {
                        while (true)
                        {
                            if (this.IsDisposed)
                                return;

                            if (_State == ListenerState.Running)
                            {
                                TrafficPair current = Get();
                                TrafficPair delta = TrafficPair.Substract(current, OnStart);
                                TrafficPair actual = TrafficPair.Union(delta, Sum);
                                BindReport(actual.OnServer, actual.OnClient);
                            }

                            Thread.Sleep(1800);
                        }
                    });

            _thread.IsBackground = true;
            _thread.Start();
        }

        private void BindReport(TrafficStatistic onServer, TrafficStatistic onClient)
        {
            string report =
                onServer.ToPlainReport("DISPATCHER", _Zero.File)
                + Environment.NewLine + Environment.NewLine
                + onClient.ToPlainReport("PROXY", _Zero.File);

            this.RunSynchronously(
                delegate
                    {
                        this.textBoxReport.Text = report;
                        this.textBoxReport.Select(0, 0);
                    }
                );
        }

        void UpdateState1(ListenerState newState)
        {
            _State = newState;
            buttonStart.Enabled = newState == ListenerState.Zero;
            buttonPause.Enabled = newState == ListenerState.Running;
            buttonContinue.Enabled = newState == ListenerState.Paused;
            buttonStop.Enabled = newState != ListenerState.Zero && newState != ListenerState.Stopped;
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            OnStart = Get();
            Sum = new TrafficPair(new TrafficStatistic(), new TrafficStatistic());
            BindReport(Sum.OnServer, Sum.OnClient);
            UpdateState1(ListenerState.Running);
        }

        private void buttonPause_Click(object sender, EventArgs e)
        {
            TrafficPair current = Get();
            TrafficPair delta = TrafficPair.Substract(current, OnStart);
            Sum = TrafficPair.Union(delta, Sum);
            BindReport(Sum.OnServer, Sum.OnClient);
            UpdateState1(ListenerState.Paused);
        }

        private void buttonContinue_Click(object sender, EventArgs e)
        {
            OnStart = Get();
            BindReport(Sum.OnServer, Sum.OnClient);
            UpdateState1(ListenerState.Running);
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            TrafficPair current = Get();
            TrafficPair delta = 
                _State == ListenerState.Paused
                ? new TrafficPair(new TrafficStatistic(), new TrafficStatistic())
                : TrafficPair.Substract(current, OnStart);
                
            Sum = TrafficPair.Union(delta, Sum);
            BindReport(Sum.OnServer, Sum.OnClient);
            UpdateState1(ListenerState.Stopped);
        }

        private TrafficPair Get()
        {
            int id = _Zero.Id;
            NetNamedPipeBinding binding = new NetNamedPipeBinding();
            binding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            binding.MaxReceivedMessageSize = Int32.MaxValue;

            var uri = TrafficPublisher.GetUri(id);
            using (var channel = new ChannelFactory<ITrafficPublisher>(binding, uri))
            {
                channel.Open(TimeSpan.FromSeconds(10));
                var proxy = channel.CreateChannel();
                TrafficStatistic onServer;
                TrafficStatistic onClient;
                proxy.Get(out onServer, out onClient);
                return new TrafficPair(onServer, onClient);
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            this.UpdateState1(ListenerState.Stopped);
        }
    }

}
